// 首先，我们补环境，起手式，肯定是先代理全局对象
// 如果说，我们通过代理器无法获得有效信息之后，这时候，就只会产生两种情况。那么我们对这两种情况，分别进行尝试
// 这一道题，因为location在我们的代码中，是我们自己定义的，全局能访问到的只有我们自己的location。
// 所以说，这个时候代理器不会失效（也就是说，目标代码一定会使用我们定义的location）
// 这个时候，我们就要考虑他是否没有访问属性( 因为我们的代理器只会在访问属性的时候生效 )
// 我们JavaScript当中，只有取描述符，不会有对象访问属性的操作。
// 这个时候尝试HOOK 取描述符函数，进行有效信息获取，即可完成此题。
function myProxy(obj,name){
    return new Proxy(obj,{
        get(target, propKey, receiver){ //拦截对象属性的读取，比如proxy.foo和proxy['foo']。
            let temp = Reflect.get(target,propKey,receiver);
            console.log(`${name} -> get ${propKey.toString()} return -> ${temp}`);
            if(typeof temp == 'object') {
                temp = myProxy(temp,name + " => " + propKey)
            }
            return temp;
        },
        set(target, propKey, value, receiver){ //拦截对象属性的设置，比如proxy.foo = v或proxy['foo'] = v，返回一个布尔值。
            const temp = Reflect.set(target,propKey,value,receiver);
            console.log(`${name} -> set ${propKey} value -> ${value}`);
            return temp;
        },
        has(target, propKey){ //拦截propKey in proxy的操作，返回一个布尔值。
            const temp = Reflect.has(target,propKey);
            console.log(`${name} -> has ${propKey.toString()}`);
            return temp;
        },
        deleteProperty(target, propKey){ //拦截delete proxy[propKey]的操作，返回一个布尔值。
            const temp = Reflect.deleteProperty(target,propKey);
            console.log(`${name} -> deleteProperty ${propKey}`);
            return temp;
        },
        ownKeys(target){ //拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环，返回一个数组。该方法返回目标对象所有自身的属性的属性名，而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
            const temp = Reflect.ownKeys(target);
            console.log(`${name} -> ownKeys ${temp}`);
            return temp;
        },
        getOwnPropertyDescriptor(target, propKey){ //拦截Object.getOwnPropertyDescriptor(proxy, propKey)，返回属性的描述对象。
            const temp = Reflect.getOwnPropertyDescriptor(target,propKey);
            return temp;
        },
        defineProperty(target, propKey, propDesc){ //拦截Object.defineProperty(proxy, propKey, propDesc）、Object.defineProperties(proxy, propDescs)，返回一个布尔值。
            const temp = Reflect.defineProperty(target,propKey,propDesc);
            return temp;
        },
        preventExtensions(target){ //拦截Object.preventExtensions(proxy)，返回一个布尔值。
            const temp = Reflect.preventExtensions(target);
            return temp;
        },
        getPrototypeOf(target){ //拦截Object.getPrototypeOf(proxy)，返回一个对象。
            const temp = Reflect.getPrototypeOf(target);
            return temp;
        },
        isExtensible(target){ //拦截Object.isExtensible(proxy)，返回一个布尔值。
            const temp = Reflect.isExtensible(target);
            return temp;
        },
        setPrototypeOf(target, proto){ //拦截Object.setPrototypeOf(proxy, proto)，返回一个布尔值。如果目标对象是函数，那么还有两种额外操作可以拦截。
            const temp = Reflect.setPrototypeOf(target,proto);
            return temp;
        },
        apply(target, object, args){ //拦截 Proxy 实例作为函数调用的操作，比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
            const temp = Reflect.apply(target, object, args);
            return temp;
        },
        construct(target, args){ //拦截 Proxy 实例作为构造函数调用的操作，比如new proxy(...args)。
            const temp = Reflect.construct(target, args);
            return temp;
        }
    })
}

document = {};
window = {};
location = {
    // href: "0"
};

Object.defineProperty(location,"href",{
    set: function (){

    },
    get: function (){
        return "";
    },
    configurable: false,
    enumerable: true
})

Object.defineProperty(Object.getOwnPropertyDescriptor(location,"href").get,"name",{
    "value": "get href",
    "writable": false,
    "enumerable": false,
    "configurable": true
});
Object.defineProperty(Object.getOwnPropertyDescriptor(location,"href").set,"name",{
    "value": "set href",
    "writable": false,
    "enumerable": false,
    "configurable": true
});

Object.defineProperty(location,"hash",{
    set: function (){

    },
    get: function (){
        return "";
    },
    configurable: false,
    enumerable: true
})


Object.defineProperty(Object.getOwnPropertyDescriptor(location,"hash").get,"name",{
    "value": "get hash",
    "writable": false,
    "enumerable": false,
    "configurable": true
});
Object.defineProperty(Object.getOwnPropertyDescriptor(location,"hash").set,"name",{
    "value": "set hash",
    "writable": false,
    "enumerable": false,
    "configurable": true
});

Object.defineProperty(location,"host",{
    set: function (){

    },
    get: function (){
        return "";
    },
    configurable: false,
    enumerable: true
})


Object.defineProperty(Object.getOwnPropertyDescriptor(location,"host").get,"name",{
    "value": "get host",
    "writable": false,
    "enumerable": false,
    "configurable": true
});
Object.defineProperty(Object.getOwnPropertyDescriptor(location,"host").set,"name",{
    "value": "set host",
    "writable": false,
    "enumerable": false,
    "configurable": true
});

Object.defineProperty(location,"protocol",{
    set: function (){

    },
    get: function (){
        return "";
    },
    configurable: false,
    enumerable: true
})


Object.defineProperty(Object.getOwnPropertyDescriptor(location,"protocol").get,"name",{
    "value": "get protocol",
    "writable": false,
    "enumerable": false,
    "configurable": true
});
Object.defineProperty(Object.getOwnPropertyDescriptor(location,"protocol").set,"name",{
    "value": "set protocol",
    "writable": false,
    "enumerable": false,
    "configurable": true
});

Object.defineProperty(location,"origin",{
    set: function (){

    },
    get: function (){
        return "";
    },
    configurable: false,
    enumerable: true
})


Object.defineProperty(Object.getOwnPropertyDescriptor(location,"origin").get,"name",{
    "value": "get origin",
    "writable": false,
    "enumerable": false,
    "configurable": true
});
Object.defineProperty(Object.getOwnPropertyDescriptor(location,"origin").set,"name",{
    "value": "set origin",
    "writable": false,
    "enumerable": false,
    "configurable": true
});

Object.defineProperty(location,"hostname",{
    set: function (){

    },
    get: function (){
        return "";
    },
    configurable: false,
    enumerable: true
})


Object.defineProperty(Object.getOwnPropertyDescriptor(location,"hostname").get,"name",{
    "value": "get hostname",
    "writable": false,
    "enumerable": false,
    "configurable": true
});
Object.defineProperty(Object.getOwnPropertyDescriptor(location,"hostname").set,"name",{
    "value": "set hostname",
    "writable": false,
    "enumerable": false,
    "configurable": true
});

//我们代理，只对属性访问有效
//如果我们的代理器没有信息输出，只有两个原因，第一个就是使用了代理器，但是没有访问属性，第二种就是，没有使用代理器
location = myProxy(location,"location");



window.location = location;

document.location = location;

location.href

//我们已知，我们使用该方法，代理器不会有数据打印。

window.myGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;


//使用该数据，可以获取到该属性的描述符，还有我们的拦截器函数，getter，setter。
Object.getOwnPropertyDescriptor = function (){
    let temp = window.myGetOwnPropertyDescriptor.apply(this,arguments);
    console.log("getOwnPropertyDescriptor",arguments,temp);
    return temp;
}

window = myProxy(window,"window");
document = myProxy(document,"document");

(function n(i, r, t, e, l, a, f, u) {
    var c, o, h, s, p, g, m, y, d, v, w, b, C, F, j, S, k, q, x, z, A, B, D, E, G, H, I, J, K, L, M, N, O, P, Q, R, T,
        U, V;
    if (this.constructor != n) {
        if (e || ((e = [this]).n = e[0], e.t = [], (o = {}).s = !1, o.v = !1, e.t.push(o), n.r = n.g = n), h = e[e.length - 1], -3 == t || -2 == t) {
            if (-2 == t) {
                for (a = 0, f = 0; i[r] > 127;) f += i[r++] - 128 << 7 * a++;
                f += i[r++] << 7 * a
            } else f = (r = (s = n(i, r, -2)).i) + (a = s.n) - 1, r += a;
            return {n: f, i: r}
        }
        if (l === n) {
            for (p = new n.g, g = [].slice.call(u), m = 0; m < a.length; m++) p[a[m]] = g[m];
            return p.arguments = u, (y = [].concat(e).concat(p)).n = f, y.t = [], n(i, r, t, y)
        }
        if (d = r || 0, c = t || i.length, v = i[d++], s = n(i, d, -2), d = s.i, s.n, w = 0, 6 == v || 10 == v ? w = 1 : 30 == v ? w = 2 : 29 == v && (w = 3), 6 == v || 10 == v || 30 == v || 29 == v) {
            for (o = e.t && e.t[e.t.length - 1], b = []; d < c;) {
                if (C = d++, s = n(i, d, -3), d = s.i, F = s.n, b.push(n(i, C, F, e)), 3 != w && e.a) return b[b.length - 1];
                if (2 == w && o && (o.v || o.s)) return b[b.length - 1]
            }
            if (2 != w) return b
        }
        if (25 == v) {
            if (j = n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e), g = n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e), n.bind) return new (n.bind.apply(j, [null].concat(g)));
            for (S = [], m = 0; m < g.length; m++) S[m] = "a[" + m + "]";
            return n.constructor("F,a", "return new F(" + S.join(",") + ")")(j, g)
        }
        if (80 != v) {
            if (125 == v) throw n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e);
            if (18 == v || 113 == v) {
                for (I = i[d++], s = n(i, d, -2), d = s.i, J = s.n, K = [], m = 0; m < J; m++) s = n(i, d, -2), d = s.i, L = s.n, K.push(L);
                return M = String.fromCharCode.apply(null, K), 113 == v || e.m ? M : l ? [e[I], M] : e[I][M]
            }
            return 0 == v ? (e.m = !0, N = n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e), e.m = !1, h[N] = e.u, n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e)) : 67 == v ? (91 == i[d++] && (O = i[d++]), O) : 34 == v ? a != f : 89 == v ? n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e) : 58 == v ? null : 57 == v ? n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e, 0, n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e), n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e)) : 78 == v ? (P = n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e), Q = n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e), e.m = !P, R = n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e), e.m = !1, l ? [Q, R] : Q[R]) : 88 == v ? n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e) ? n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e) : (s = n(i, ++d, -3), d = s.i, s.n, n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e)) : 95 == v ? (T = n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e, !0), U = n(i, d++, (s = n(i, d, -3), d = s.i, s.n), e), T instanceof n.constructor ? n.apply.call(T, e[0].n, U) : (V = T[0][T[1]], T[0] instanceof n.g ? n.apply.call(V, e.n, U) : n.apply.call(V, T[0], U))) : void 0
        }
        k = d++, s = n(i, d, -3), d = s.i, q = s.n, x = d++, s = n(i, d, -3), d = s.i, z = s.n, A = d++, s = n(i, d, -3), d = s.i, B = s.n;
        try {
            if (D = n(i, k, q, e), e.a) return D
        } catch (W) {
            if (e.u = W, E = n(i, x, z, e), e.a) return E
        } finally {
            if (G = e.a, e.a = !1, H = n(i, A, B, e), e.a) return H;
            e.a = G
        }
    }
})([6, 198, 8, 10, 195, 8, 80, 192, 8, 30, 252, 7, 30, 249, 7, 88, 154, 1, 57, 127, 34, 0, 78, 111, 67, 2, 91, 0, 78, 97, 67, 2, 91, 0, 95, 84, 78, 42, 67, 2, 91, 0, 18, 8, 0, 6, 79, 98, 106, 101, 99, 116, 18, 26, 0, 24, 103, 101, 116, 79, 119, 110, 80, 114, 111, 112, 101, 114, 116, 121, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 29, 38, 78, 28, 67, 2, 91, 0, 18, 10, 0, 8, 100, 111, 99, 117, 109, 101, 110, 116, 18, 10, 0, 8, 108, 111, 99, 97, 116, 105, 111, 110, 113, 6, 0, 4, 104, 114, 101, 102, 18, 5, 0, 3, 103, 101, 116, 18, 6, 0, 4, 110, 97, 109, 101, 113, 10, 0, 8, 103, 101, 116, 32, 104, 114, 101, 102, 30, 21, 30, 19, 125, 17, 25, 15, 18, 7, 0, 5, 69, 114, 114, 111, 114, 29, 4, 113, 2, 0, 0, 58, 0, 88, 154, 1, 57, 127, 34, 0, 78, 111, 67, 2, 91, 0, 78, 97, 67, 2, 91, 0, 95, 84, 78, 42, 67, 2, 91, 0, 18, 8, 0, 6, 79, 98, 106, 101, 99, 116, 18, 26, 0, 24, 103, 101, 116, 79, 119, 110, 80, 114, 111, 112, 101, 114, 116, 121, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 29, 38, 78, 28, 67, 2, 91, 0, 18, 10, 0, 8, 100, 111, 99, 117, 109, 101, 110, 116, 18, 10, 0, 8, 108, 111, 99, 97, 116, 105, 111, 110, 113, 6, 0, 4, 104, 97, 115, 104, 18, 5, 0, 3, 103, 101, 116, 18, 6, 0, 4, 110, 97, 109, 101, 113, 10, 0, 8, 103, 101, 116, 32, 104, 97, 115, 104, 30, 21, 30, 19, 125, 17, 25, 15, 18, 7, 0, 5, 69, 114, 114, 111, 114, 29, 4, 113, 2, 0, 0, 58, 0, 88, 154, 1, 57, 127, 34, 0, 78, 111, 67, 2, 91, 0, 78, 97, 67, 2, 91, 0, 95, 84, 78, 42, 67, 2, 91, 0, 18, 8, 0, 6, 79, 98, 106, 101, 99, 116, 18, 26, 0, 24, 103, 101, 116, 79, 119, 110, 80, 114, 111, 112, 101, 114, 116, 121, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 29, 38, 78, 28, 67, 2, 91, 0, 18, 10, 0, 8, 100, 111, 99, 117, 109, 101, 110, 116, 18, 10, 0, 8, 108, 111, 99, 97, 116, 105, 111, 110, 113, 6, 0, 4, 104, 111, 115, 116, 18, 5, 0, 3, 103, 101, 116, 18, 6, 0, 4, 110, 97, 109, 101, 113, 10, 0, 8, 103, 101, 116, 32, 104, 111, 115, 116, 30, 21, 30, 19, 125, 17, 25, 15, 18, 7, 0, 5, 69, 114, 114, 111, 114, 29, 4, 113, 2, 0, 0, 58, 0, 88, 163, 1, 57, 135, 1, 34, 0, 78, 115, 67, 2, 91, 0, 78, 101, 67, 2, 91, 0, 95, 88, 78, 42, 67, 2, 91, 0, 18, 8, 0, 6, 79, 98, 106, 101, 99, 116, 18, 26, 0, 24, 103, 101, 116, 79, 119, 110, 80, 114, 111, 112, 101, 114, 116, 121, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 29, 42, 78, 28, 67, 2, 91, 0, 18, 10, 0, 8, 100, 111, 99, 117, 109, 101, 110, 116, 18, 10, 0, 8, 108, 111, 99, 97, 116, 105, 111, 110, 113, 10, 0, 8, 112, 114, 111, 116, 111, 99, 111, 108, 18, 5, 0, 3, 103, 101, 116, 18, 6, 0, 4, 110, 97, 109, 101, 113, 14, 0, 12, 103, 101, 116, 32, 112, 114, 111, 116, 111, 99, 111, 108, 30, 21, 30, 19, 125, 17, 25, 15, 18, 7, 0, 5, 69, 114, 114, 111, 114, 29, 4, 113, 2, 0, 0, 58, 0, 88, 159, 1, 57, 131, 1, 34, 0, 78, 113, 67, 2, 91, 0, 78, 99, 67, 2, 91, 0, 95, 86, 78, 42, 67, 2, 91, 0, 18, 8, 0, 6, 79, 98, 106, 101, 99, 116, 18, 26, 0, 24, 103, 101, 116, 79, 119, 110, 80, 114, 111, 112, 101, 114, 116, 121, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 29, 40, 78, 28, 67, 2, 91, 0, 18, 10, 0, 8, 100, 111, 99, 117, 109, 101, 110, 116, 18, 10, 0, 8, 108, 111, 99, 97, 116, 105, 111, 110, 113, 8, 0, 6, 111, 114, 105, 103, 105, 110, 18, 5, 0, 3, 103, 101, 116, 18, 6, 0, 4, 110, 97, 109, 101, 113, 12, 0, 10, 103, 101, 116, 32, 111, 114, 105, 103, 105, 110, 30, 21, 30, 19, 125, 17, 25, 15, 18, 7, 0, 5, 69, 114, 114, 111, 114, 29, 4, 113, 2, 0, 0, 58, 0, 88, 163, 1, 57, 135, 1, 34, 0, 78, 115, 67, 2, 91, 0, 78, 101, 67, 2, 91, 0, 95, 88, 78, 42, 67, 2, 91, 0, 18, 8, 0, 6, 79, 98, 106, 101, 99, 116, 18, 26, 0, 24, 103, 101, 116, 79, 119, 110, 80, 114, 111, 112, 101, 114, 116, 121, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 29, 42, 78, 28, 67, 2, 91, 0, 18, 10, 0, 8, 100, 111, 99, 117, 109, 101, 110, 116, 18, 10, 0, 8, 108, 111, 99, 97, 116, 105, 111, 110, 113, 10, 0, 8, 104, 111, 115, 116, 110, 97, 109, 101, 18, 5, 0, 3, 103, 101, 116, 18, 6, 0, 4, 110, 97, 109, 101, 113, 14, 0, 12, 103, 101, 116, 32, 104, 111, 115, 116, 110, 97, 109, 101, 30, 21, 30, 19, 125, 17, 25, 15, 18, 7, 0, 5, 69, 114, 114, 111, 114, 29, 4, 113, 2, 0, 0, 58, 0, 89, 50, 95, 48, 78, 22, 67, 2, 91, 0, 18, 9, 0, 7, 99, 111, 110, 115, 111, 108, 101, 18, 5, 0, 3, 108, 111, 103, 29, 22, 113, 20, 0, 6, 175, 231, 1, 131, 177, 1, 161, 208, 1, 140, 181, 2, 144, 196, 1, 159, 165, 1, 0, 61, 18, 3, 0, 1, 101, 30, 54, 30, 52, 89, 50, 95, 48, 78, 22, 67, 2, 91, 0, 18, 9, 0, 7, 99, 111, 110, 115, 111, 108, 101, 18, 5, 0, 3, 108, 111, 103, 29, 22, 113, 20, 0, 6, 175, 231, 1, 131, 177, 1, 161, 208, 1, 140, 181, 2, 177, 178, 1, 165, 154, 2, 58, 0]);